import { lib, game, ui, get, ai, _status } from '../../../noname.js';
import { config } from '../myExtension/config.js'
import { swTool } from "../main/swTool.js";
import { swFunc } from "../main/swFunc.js";
import { DIY } from '../character/DIY.js';
import { hemengaozhan } from '../mode/hemengaozhan/hemengaozhan.js';
import { langrensha } from '../mode/langrensha/langrensha.js';
import { NonameAssembly } from '../../../noname/library/assembly/index.js';

//自定义的小卡片格式
ui.create.buttonPresets.vcardx = swFunc.vcardx
//复制房间禁将（完全替换，需要适配）
ui.create.roomInfo = swFunc.roomInfo
//来源于岁儿大佬的弹幕UI系统
ui.create.danmu = swFunc.createDanMu

//自定义的身份列表（call了旧的，基本无需适配）
get.identityList = swFunc.identityList
//旧版modetrans，用于显示房间名称颜色（完全替换，需要适配）
get.modetrans = swFunc.modetrans
//播放全场视频（硬控
game.playSkillVideo = swFunc.playSkillVideo

//手气卡（完全替换，需要适配）
game.replaceHandcards = swTool.replaceHandcards
//从扩展包里加载自定义模式的（完全替换，需要适配）
game.loadModeAsync = swTool.loadModeAsync

lib.hooks.gameStart = new NonameAssembly('gameStart')
//导入联机模式
swTool.addConnectMode('合盟鏖战', 'hemengaozhan', hemengaozhan);
swTool.addConnectMode('狼人杀', 'langrensha', langrensha);

swTool.getAllFilePaths(`extension/${swTool.extensionName}/assets`, (paths) => {
	 _status.syncFiles = paths;
});

//TODO:手气卡逻辑重写
game.phaseLoop = function (player) {
	//如果没换过手气卡就换一下
    if (!swTool.replaceHandcardsOver) {
        game.replaceHandcards(game.players);
	}
	//原来的逻辑
    const next = game.createEvent("phaseLoop");  
    next.player = player;
    next._isStandardLoop = true;
    next.setContent("phaseLoop");
}

//TODO: 这一坨早晚得改
const _oldSend = game.send
game.send = function () {
	//game.callHook("sendBegin", ...arguments)
	if (arguments[1] == 'config' && swTool.newConnectMode.includes(arguments[2].mode)) {
		const modifiedArgs = Array.prototype.slice.call(arguments) //我就偷偷地替换你一下，应该没人发现吧
		const configCopy = JSON.parse(JSON.stringify(arguments[2]))
		if (arguments[0] == 'server') {
			configCopy.mode = `<span style="color: yellow;">${get.translation(arguments[2].mode)}</span>`
		}
		modifiedArgs[2] = configCopy

		_oldSend.call(this, ...modifiedArgs)
		//game.callHook("sendEnd", ...modifiedArgs)
	}
	else {
		_oldSend.call(this, ...arguments)
		//game.callHook("sendEnd", ...arguments)
	}
}

//初始化服务端消息事件
const _oldServerInit = lib.message.server.init
swTool.comboObject(lib.message.server, {
	changeState(player, stateName = undefined, clear = false) {
		game.changeState(player, stateName, clear)
	},
	changeSkinFun(player) {
		game.broadcastAll((player) => {
			if (lib.characterSubstitute[player.firstCharacter]) {
				var num = Math.floor(Math.random() * lib.characterSubstitute[player.firstCharacter].length);
				player.changeSkin({ characterName: player.firstCharacter }, player.firstCharacter + "_shadow" + num);
			}
		}, player);
		game.log(`#y${player.nickname}`, "换肤成功！");
	},
	initAvatar(id, avatar) {
		game.broadcastAll((player, avatar, nickname) => {
			const character = lib.character[avatar] || ['male', 'qun', 4, [], []]
			const id = nickname + player.playerid
			lib.character[id] = character.slice()
			lib.character[id][2] = 4
			lib.character[id][3] = []
			if (!lib.character[id][4]) {
				lib.character[id][4] = []
			}
			lib.character[id][4].remove('hiddenSkill')
			lib.character[id][4].push(`character:${avatar}`)
			lib.translate[id] = nickname.replace('※', '')
			player.init(id)
			player.update()
		}, lib.playerOL[id], avatar, this.nickname)
	},
	getObserveEnterPer() {
		this.send(
			JSON.stringify({
				type: "getObserveEnterPer",
				data: lib.configOL.observePermission,
			})
		);
	},
	observeRequestEnter(nickname, ws, playerId) {
		const player = lib.playerOL[playerId]
		if(!player || !lib.configOL.observePermission[playerId]) {
			game.me.chat(`玩家 <span style="font-weight: bold; color: rgb(126, 180, 255)">${get.plainText(nickname)}</span>` + " 发起了一个非法的入场请求！")
			return
		}
		game.me.chat(`玩家 <span style="font-weight: bold; color: rgb(126, 180, 255)">${get.plainText(nickname)}</span>` + " 请求入场，入场角色：" + (player?.node?.name?.textContent || "[非法角色]"))
		lib.configOL.observeRequesting ??= []
		lib.configOL.observeRequesting.push({nickname: nickname, ws: ws, playerId: playerId})
	},
	init(version, config, banned_info) {
		//TODO:此处是玩家联机进入房间时的初始化逻辑，可以判断一些事情
		this.nickname = config.nickname
		this.send((tool, func) => {
			window.swTool = tool;
			game.loadModeAsync = tool.loadModeAsync;
			game.playSkillVideo = func;
		}, swTool, game.playSkillVideo);
		swTool.executeConnect({ player: this, version, config, banned_info });
		swTool.modeCharacter({ player: this, version, config, banned_info });
		swTool.modeInit(this)
		if (!_status.waitingForPlayer && _status.extensionMode?.reinit && typeof _status.extensionMode.reinit === "function") {
			const args = Array.isArray(_status.reloadResource) ? _status.reloadResource : [];
			if(args.length > 0) this.send(_status.extensionMode.reinit, ...args);
		}
		return _oldServerInit.call(this, version, config, banned_info)
		//call后开始loadmode
	},
	chat(id, str) {
		const limitCount = parseInt(lib.config?.[swTool.myURL() + "game_sayLimit"]) || 0;
		if(limitCount) {
			if (!this._chatLogs) {
				this._chatLogs = [];
			}
			const now = Date.now();
			const limitPer = 5000;
			const recent = this._chatLogs.filter(ts => now - ts < limitPer);

			if (recent.length >= limitCount) {
				//TODO: 整顿弹幕
				this.send(ui.create.danmu, '', '提示', '您的发言已被限流！');
				return;
			}
			recent.push(now);
			this._chatLogs = recent;
		}
		const player = swTool.getPlayer(id);
		if (player) {
			if (player === game.me && this.mainHost !== 'mainHost') {
				lib.element.player.chat.call(player, str)
			} else {
				player.chat(str)
			}
		} else if (lib.node.observing.includes(this) || swTool.observingId?.includes(this)) {
			const name = this.nickname || arguments[arguments.length - 1]
			if (lib.config[`${swTool.myURL()}game_cdown`]) {
				const prefix = lib.node.observing.includes(this) ? '<span style="color: rgb(42, 187, 223);">（旁观）</span>' : '<span style="color:red;">（被控制）</span>'
				game.broadcastAll((func, prefix, name, str) => {
					name = get.plainText(name)
					if (!swTool.isEmotion(str)) {
						str = get.plainText(str)
					}
					func(prefix, name, str)
					str = str.replace(/##assetURL##/g, lib.assetURL);
					const info = [prefix + name, str];
					lib.chatHistory.push(info);
					if (_status.addChatEntry) {
						if (_status.addChatEntry._origin.parentNode) {
							_status.addChatEntry(info, false);
						} else {
							delete _status.addChatEntry;
						}
					}
				}, ui.create.danmu, prefix, name, str)
			}
		}
	},
	emotion(id, pack, emotion, name) {
		const limitCount = parseInt(lib.config?.[swTool.myURL() + "game_sayLimit"]) || 0;
		if(limitCount) {
			if (!this._chatLogs) {
				this._chatLogs = [];
			}
			const now = Date.now();
			const limitPer = 5000;
			const recent = this._chatLogs.filter(ts => now - ts < limitPer);

			if (recent.length >= limitCount) {
				//TODO: 整顿弹幕
				this.send(ui.create.danmu, '', '提示', '您的发言已被限流！');
				return;
			}
			recent.push(now);
			this._chatLogs = recent;
		}
		const player = swTool.getPlayer(id);
		if (player) {
			player.emotion(pack, emotion)
		} else if (lib.node.observing.includes(this) || swTool.observingId.includes(this)) {
			const str = '<img src="##assetURL##image/emotion/' + pack + '/' + emotion + '.gif" width="50" height="50">';
			lib.message.server.chat.call(this, this.id, str, name)
		}
	},
})

const functions = {
	cdown() {
		const _oldPlayerSay = lib.element.player.say
		lib.element.player.say = function (str) {
			const player = this
			let nickname = (this.tempNickname ? `<span style="color:green;">（${this.tempNickname}控制的${this.nickname}）</span>` : '') || this.nickname || get.translation(this.name) + "[电脑玩家]" || "[电脑玩家]",
				prefix = '';
			game.addVideo('say', player, {
				nickname,
				str
			})
			Promise.resolve().then(() => {
				game.broadcastAll((danmu, prefix, name, str) => {
					danmu(prefix, name, str)
				}, ui.create.danmu, prefix, nickname, str)
			})
			return _oldPlayerSay.call(this, ...arguments)
		}
	},
	skillInfo() {
		const _oldGamelog = game.log
		game.log = function () {
			const args = Array.from(arguments)
			const bool = args.some(s => typeof s === 'string' && (s.includes('发动了') || s.includes('将势力') || s.includes('的判定结果为')))
			if (bool) {
				const color = new Map([
					['r', 'fire'],
					['y', 'yellow'],
					['g', 'green'],
					['b', 'green']
				]);
				let info = ''
				args.forEach(c => {
					const itemtype = get.itemtype(c)
					const trans = get.translation(c)
					if (c[0] === '#') {
						info += `<span class="${color.get(c[1]) || ''}text">${get.translation(c.slice(2))}</span>`;
					} else if (typeof c === 'string' && c[0] == '【' && c[c.length - 1] == '】') {
						info += `<span class="firetext">${trans}</span>`;
					} else if (!itemtype) {
						info += trans
					} else if (itemtype.includes('player')) {
						info += `<span class="greentext">${trans}</span>`;
					} else if (itemtype.includes('card')) {
						info += `<span class="yellowtext">${trans}</span>`;
					} else {
						info += trans
					}
				})
				const sendInfo = info => {
					if (!ui.skillInfos) {
						ui.skillInfos = ui.create.div('.skillInofss', ui.window)
						const style = document.createElement('style')
						style.innerHTML = /*css*/`
							.skillInofss {
								width: 50%;
								bottom: -5%;
    							height: 50%;
								overflow: auto;
								font-family: "shousha" !important;
								z-index: 10;
								pointer-events: none;
								text-align: center;
								display: flex;
								flex-direction: column;
								align-items: center;
								transform: translate(-50%, -50%);
								left: 50%;
							}

							.skillInofss .skillInfoShwo {
								text-shadow: #000000 0 0 2px;
								font-family: "shousha" !important;
								pointer-events: none;
								text-align: center;
								transition: all 0.5s;
								position: relative;
								font-size: 18px;
								line-height: 21px;
								background: linear-gradient(to right, transparent 0%, rgba(0, 0, 0, 0.5) 10%, rgba(0, 0, 0, 0.5) 90%, transparent 100%);
								background-size: 100% 100%;
								animation: fadeInUp 0.5s ease;
								display: inline-block;
								width: fit-content;
							}

							@keyframes fadeOutDown {
							  0% {
								opacity: 1;
								transform: perspective(400px) rotateX(0deg) translateY(0);
							  }
							  100% {
								opacity: 0;
								transform: perspective(400px) rotateX(60deg) translateY(30px);
							  }
							}

							.fade-out-down {
							  animation: fadeOutDown 0.5s ease forwards;
							  transform-style: preserve-3d;
							  backface-visibility: hidden;
							}

							@keyframes fadeInUp {
								0% {
									opacity: 0;
									transform: translateY(20px);
								}
								100% {
									opacity: 1;
									transform: translateY(0);
								}
							}
						`

						document.head.appendChild(style)
					}
					setTimeout(node => node.delete(), 3000, ui.create.div('.skillInfoShwo', info, ui.skillInfos));
				}
				if (lib?.node?.clients) {
					lib.node.clients.forEach(c => {
						c.gameOptions ??= {}
						if (!c.gameOptions.infoStyle) {
							c.send((sendInfo) => game.sendInfo = sendInfo, sendInfo)
							c.gameOptions.infoStyle = true
						}
					})
				}
				if (!game.online) sendInfo(info)
				game.broadcast((info) => { game.sendInfo(info) }, info)
			}
			return _oldGamelog.call(this, ...arguments)
		}
		game.log.skillInfo = true
	},
	tphaseTip() {
		swTool.globalSkills._tphaseTip = {
			trigger: {
				global: ['phaseBeginStart', 'phaseZhunbeiBefore', 'phaseJudgeBefore', 'phaseDrawBefore', 'phaseUseBefore', 'phaseDiscardBefore', 'phaseJieshuBefore', 'phaseEnd']
			},
			filter(event, player) {
				return event.player && lib.config[`${swTool.myURL()}game_tphaseTip`]
			},
			async content(event, trigger) {
				game.broadcastAll((phasename, player) => {
					if (phasename === 'phaseEnd') {
						if (player.node.tphaseTip) {
							player.node.tphaseTip.innerHTML = ''
						}
					}
					else if (phasename === 'phaseBeginStart') {//有人的回合开始时也刷新一下其他人的阶段提示。TODO:还要刷新一下人物高光
						game.players.concat(game.dead).forEach(current => {
							if (current.node.tphaseTip && current != player) {
								current.node.tphaseTip.innerHTML = ''
								current.classList.remove('glow_phase')
							}
						})
					}

					if (phasename !== 'phaseEnd') {
						const phase = {
							phaseBeginStart: '回合开始',
							phaseZhunbeiBefore: '准备阶段',
							phaseJudgeBefore: '判定阶段',
							phaseDrawBefore: '摸牌阶段',
							phaseUseBefore: '出牌阶段',
							phaseDiscardBefore: '弃牌阶段',
							phaseJieshuBefore: '结束阶段'
						}
						const name = phase[phasename]
						if (!player.node.tphaseTip) {
							const addStyle = () => {
								if (!_status.phaseStyle) {
									_status.phaseStyle = true
									const tphaseTip = document.createElement('style')
									tphaseTip.innerHTML = `
									.player > .tphaseTip {
										width: 100%;
										max-width: 150px;
										text-align: center;
										bottom: -17px;
										font-family: 'shousha', 'songti', "宋体";
										color: rgb(244 235 187);
										pointer-events: none;
										text-shadow: 0 0 3px #7e5200, 0 0 6px #7e5200, 0 0 9px #7e5200;
										background: radial-gradient(circle at center, #ffdd00, #ffffff00);
										border-radius: 3px;
										display: inline-block;
										font-weight: bold;
										transition: all 0s !important;
										z-index: 200;
									}
									.player[data-position="0"] .tphaseTip {
										bottom: 102%;
									}
									`
									document.head.appendChild(tphaseTip)
								}
							}
							addStyle()
							player.node.tphaseTip = ui.create.div('.tphaseTip', '', player)
							if (lib?.node?.clients) {
								lib.node.clients.forEach(c => {
									c.gameOptions ??= {}
									//TODO: 简化对style的判断
									if (!c.gameOptions.phaseTip) {
										c.send(addStyle)
										c.gameOptions.phaseTip = true
									}
								})
							}
						}
						player.node.tphaseTip.textContent = name
						const pdiv = player.node.tphaseTip
						switch (name) {
							case '判定阶段':
								pdiv.style.color = 'rgb(244 187 239)';
								pdiv.style.textShadow = '0 0 3px #7b0072, 0 0 6px #7b0072, 0 0 9px #7b0072';
								pdiv.style.background = 'radial-gradient(circle at center, #ff00eb, #ffffff00)';
								break;
							case '摸牌阶段':
								pdiv.style.color = 'rgb(187 244 187)';
								pdiv.style.textShadow = '0 0 3px #094600, 0 0 6px #094600, 0 0 9px #094600';
								pdiv.style.background = 'radial-gradient(circle at center, #23ff00, #ffffff00)';
								break;
							case '出牌阶段':
								pdiv.style.color = 'rgb(187 209 244)';
								pdiv.style.textShadow = '0 0 3px #001b46, 0 0 6px #001b46, 0 0 9px #001b46';
								pdiv.style.background = 'radial-gradient(circle at center, #0066ff, #ffffff00)';
								break;
							case '结束阶段':
								pdiv.style.color = 'rgb(244 187 187';
								pdiv.style.textShadow = '0 0 3px #460000, 0 0 6px #460000, 0 0 9px #460000';
								pdiv.style.background = 'radial-gradient(circle at center, #ff0000, #ffffff00)';
								break;
							case '弃牌阶段':
							case '准备阶段':
							case '回合开始':
							default:
								pdiv.style.color = 'rgb(244 235 187)';
								pdiv.style.textShadow = '0 0 3px #7e5200, 0 0 6px #7e5200, 0 0 9px #7e5200';
								pdiv.style.background = 'radial-gradient(circle at center, #ffdd00, #ffffff00)';
						}
					}
				}, event.triggername, trigger.player)
			},
			direct: true,
			popup: false,
			forced: true,
			forceDie: true,
			charlotte: true,
			superCharlotte: true,
			ruleSkill: true,
			locked: true,
		}
	},
	extensionClose() {
		lib.message.client.opened = function () {
			game.send(
				"init",
				lib.versionOL,
				{
					id: "" || game.onlineID,
					onlineKey: game.onlineKey,
					avatar: lib.config.connect_avatar,
					nickname: get.connectNickname(),
					versionLocal: lib.version,
					extension: false,
				},
				lib.config.banned_info
			);
			if (ui.connecting && !ui.connecting.splashtimeout) {
				ui.connecting.firstChild.innerHTML = "重连成功";
			}
		}
		//TODO: 这里可以改为收到从主机发来的函数后哦替换里面存在的lib.extension

	},
	diyRoom() {
		game.send = function () {
			//game.callHook("sendBegin", ...arguments)
			if (arguments[1] == 'config') {
				const modifiedArgs = Array.prototype.slice.call(arguments) //我就偷偷地替换你一下，应该没人发现吧
				const configCopy = JSON.parse(JSON.stringify(arguments[2]))
				if (arguments[0] == 'server') {
					const color = lib.config[`${swTool.myURL()}info_diyRoomColor`]
					const name = lib.config[`${swTool.myURL()}info_diyRoomName`]
					if (color == "normal") configCopy.mode = name
					else if (color == "colors") {
						configCopy.mode = `<span class="sw_infoText">${name}</span>`
					}
					else configCopy.mode = `<span style="color: ${color};">${name}</span>`
					configCopy.cardPack = lib.config[`${swTool.myURL()}info_diyRoomTag`].trim().split(/\s+/)
				}
				modifiedArgs[2] = configCopy

				_oldSend.call(this, ...modifiedArgs)
				//game.callHook("sendEnd", ...modifiedArgs)
			}
			else {
				_oldSend.call(this, ...arguments)
				//game.callHook("sendEnd", ...arguments)
			}

		}
	},
	continuousInteraction() {
		//TODO: 这里改为修改界面中的内容，不要复制这么一大堆原函数
		lib.translate.flowerSpam = "花篮子"
		lib.translate.eggSpam = "蛋篮子"
		lib.translate.wineSpam = "连续酒杯"
		lib.translate.shoeSpam = "连续拖鞋"
		get.nodeintro = function(node, simple, evt) {
			var uiintro = ui.create.dialog("hidden", "notouchscroll");
			if (node.classList.contains("player") && !node.name) {
				return uiintro;
			}
			var i, translation, intro, str;
			if (node._nointro) return;
			if (typeof node._customintro == "function") {
				if (node._customintro(uiintro, evt) === false) return;
				if (evt) lib.placePoppedDialog(uiintro, evt);
			} else if (Array.isArray(node._customintro)) {
				var caption = node._customintro[0];
				var content = node._customintro[1];
				if (typeof caption == "function") {
					caption = caption(node);
				}
				if (typeof content == "function") {
					content = content(node);
				}
				uiintro.add(caption);
				uiintro.add('<div class="text center" style="padding-bottom:5px">' + content + "</div>");
			} else if (node.classList.contains("player") || node.linkplayer) {
				if (node.linkplayer) {
					node = node.link;
				}
				let capt = get.translation(node.name);
				const characterInfo = get.character(node.name),
					sex = node.sex || characterInfo[0];
				if (sex && sex != "unknown" && lib.config.show_sex) capt += `&nbsp;&nbsp;${sex == "none" ? "无" : get.translation(sex)}`;
				const group = node.group;
				if (group && group != "unknown" && lib.config.show_group) capt += `&nbsp;&nbsp;${get.translation(group)}`;
				uiintro.add(capt);

				if (lib.characterTitle[node.name]) {
					uiintro.addText(get.colorspan(lib.characterTitle[node.name]));
				}

				if (get.characterInitFilter(node.name)) {
					const initFilters = get.characterInitFilter(node.name).filter(tag => {
						if (!lib.characterInitFilter[node.name]) return true;
						return lib.characterInitFilter[node.name](tag) !== false;
					});
					if (initFilters.length) {
						const str = initFilters.reduce((strx, stry) => strx + lib.InitFilter[stry] + "<br>", "").slice(0, -4);
						uiintro.addText(str);
					}
				}

				if (!node.noclick) {
					const allShown = node.isUnderControl() || (!game.observe && game.me && game.me.hasSkillTag("viewHandcard", null, node, true));
					const shownHs = node.getShownCards();
					if (shownHs.length) {
						uiintro.add('<div class="text center">明置的手牌</div>');
						uiintro.addSmall(shownHs);
						if (allShown) {
							var hs = node.getCards("h");
							hs.removeArray(shownHs);
							if (hs.length) {
								uiintro.add('<div class="text center">其他手牌</div>');
								uiintro.addSmall(hs);
							}
						}
					} else if (allShown) {
						var hs = node.getCards("h");
						if (hs.length) {
							uiintro.add('<div class="text center">手牌</div>');
							uiintro.addSmall(hs);
						}
					}
				}

				var skills = node.getSkills(null, false, false).slice(0);
				var skills2 = game.filterSkills(skills, node);
				if (node == game.me && node.hiddenSkills.length) {
					skills.addArray(node.hiddenSkills);
				}
				for (var i in node.disabledSkills) {
					if (node.disabledSkills[i].length == 1 && node.disabledSkills[i][0] == i + "_awake" && !node.hiddenSkills.includes(i)) {
						skills.add(i);
					}
				}
				for (i = 0; i < skills.length; i++) {
					if (lib.skill[skills[i]] && (lib.skill[skills[i]].nopop || lib.skill[skills[i]].equipSkill)) continue;
					if (lib.translate[skills[i] + "_info"]) {
						if (lib.translate[skills[i] + "_ab"]) translation = lib.translate[skills[i] + "_ab"];
						else {
							translation = get.translation(skills[i]);
							if (!lib.skill[skills[i]].nobracket) translation = `【${translation.slice(0, 2)}】`;
						}
						if (node.forbiddenSkills[skills[i]]) {
							var forbidstr = '<div style="opacity:0.5"><div class="skill">' + translation + "</div><div>";
							if (node.forbiddenSkills[skills[i]].length) {
								forbidstr += "（与" + get.translation(node.forbiddenSkills[skills[i]]) + "冲突）<br>";
							} else {
								forbidstr += "（双将禁用）<br>";
							}
							forbidstr += get.skillInfoTranslation(skills[i], node) + "</div></div>";
							uiintro.add(forbidstr);
						} else if (!skills2.includes(skills[i])) {
							if (lib.skill[skills[i]].preHidden && get.mode() == "guozhan") {
								uiintro.add('<div><div class="skill" style="opacity:0.5">' + translation + '</div><div><span style="opacity:0.5">' + get.skillInfoTranslation(skills[i], node) + '</span><br><div class="underlinenode on gray" style="position:relative;padding-left:0;padding-top:7px">预亮技能</div></div></div>');
								var underlinenode = uiintro.content.lastChild.querySelector(".underlinenode");
								if (_status.prehidden_skills.includes(skills[i])) {
									underlinenode.classList.remove("on");
								}
								underlinenode.link = skills[i];
								underlinenode.listen(ui.click.hiddenskill);
							} else uiintro.add('<div style="opacity:0.5"><div class="skill">' + translation + "</div><div>" + get.skillInfoTranslation(skills[i], node) + "</div></div>");
						} else if (lib.skill[skills[i]].temp || !node.skills.includes(skills[i]) || lib.skill[skills[i]].thundertext) {
							if (lib.skill[skills[i]].frequent || lib.skill[skills[i]].subfrequent) {
								uiintro.add('<div><div class="skill thundertext thunderauto">' + translation + '</div><div class="thundertext thunderauto">' + get.skillInfoTranslation(skills[i], node) + '<br><div class="underlinenode on gray" style="position:relative;padding-left:0;padding-top:7px">自动发动</div></div></div>');
								var underlinenode = uiintro.content.lastChild.querySelector(".underlinenode");
								if (lib.skill[skills[i]].frequent) {
									if (lib.config.autoskilllist.includes(skills[i])) {
										underlinenode.classList.remove("on");
									}
								}
								if (lib.skill[skills[i]].subfrequent) {
									for (var j = 0; j < lib.skill[skills[i]].subfrequent.length; j++) {
										if (lib.config.autoskilllist.includes(skills[i] + "_" + lib.skill[skills[i]].subfrequent[j])) {
											underlinenode.classList.remove("on");
										}
									}
								}
								if (lib.config.autoskilllist.includes(skills[i])) {
									underlinenode.classList.remove("on");
								}
								underlinenode.link = skills[i];
								underlinenode.listen(ui.click.autoskill2);
							} else {
								uiintro.add('<div><div class="skill thundertext thunderauto">' + translation + '</div><div class="thundertext thunderauto">' + get.skillInfoTranslation(skills[i], node) + "</div></div>");
							}
						} else if (lib.skill[skills[i]].frequent || lib.skill[skills[i]].subfrequent) {
							uiintro.add('<div><div class="skill">' + translation + "</div><div>" + get.skillInfoTranslation(skills[i], node) + '<br><div class="underlinenode on gray" style="position:relative;padding-left:0;padding-top:7px">自动发动</div></div></div>');
							var underlinenode = uiintro.content.lastChild.querySelector(".underlinenode");
							if (lib.skill[skills[i]].frequent) {
								if (lib.config.autoskilllist.includes(skills[i])) {
									underlinenode.classList.remove("on");
								}
							}
							if (lib.skill[skills[i]].subfrequent) {
								for (var j = 0; j < lib.skill[skills[i]].subfrequent.length; j++) {
									if (lib.config.autoskilllist.includes(skills[i] + "_" + lib.skill[skills[i]].subfrequent[j])) {
										underlinenode.classList.remove("on");
									}
								}
							}
							if (lib.config.autoskilllist.includes(skills[i])) {
								underlinenode.classList.remove("on");
							}
							underlinenode.link = skills[i];
							underlinenode.listen(ui.click.autoskill2);
						} else if (lib.skill[skills[i]].clickable && node.isIn() && node.isUnderControl(true)) {
							var intronode = uiintro.add('<div><div class="skill">' + translation + "</div><div>" + get.skillInfoTranslation(skills[i], node) + '<br><div class="menubutton skillbutton" style="position:relative;margin-top:5px">点击发动</div></div></div>').querySelector(".skillbutton");
							if (!_status.gameStarted || (lib.skill[skills[i]].clickableFilter && !lib.skill[skills[i]].clickableFilter(node))) {
								intronode.classList.add("disabled");
								intronode.style.opacity = 0.5;
							} else {
								intronode.link = node;
								intronode.func = lib.skill[skills[i]].clickable;
								intronode.classList.add("pointerdiv");
								intronode.listen(ui.click.skillbutton);
							}
						} else {
							uiintro.add('<div><div class="skill">' + translation + "</div><div>" + get.skillInfoTranslation(skills[i], node) + "</div></div>");
						}
						if (lib.translate[skills[i] + "_append"]) {
							uiintro._place_text = uiintro.add('<div class="text">' + lib.translate[skills[i] + "_append"] + "</div>");
						}
					}
				}
				// if(get.is.phoneLayout()){
				// 	var storage=node.storage;
				// 	for(i in storage){
				// 		if(get.info(i)&&get.info(i).intro){
				// 			intro=get.info(i).intro;
				// 			if(node.getSkills().concat(lib.skill.global).includes(i)==false&&!intro.show) continue;
				// 			var name=intro.name?intro.name:get.translation(i);
				// 			if(typeof name=='function'){
				// 				name=name(storage[i],node);
				// 			}
				// 			translation='<div><div class="skill">『'+name.slice(0,2)+'』</div><div>';
				// 			var stint=get.storageintro(intro.content,storage[i],node,null,i);
				// 			if(stint){
				// 				translation+=stint+'</div></div>';
				// 				uiintro.add(translation);
				// 			}
				// 		}
				// 	}
				// }

				if (lib.config.right_range && _status.gameStarted) {
					uiintro.add(ui.create.div(".placeholder"));
					var table, tr, td;
					table = document.createElement("table");
					tr = document.createElement("tr");
					table.appendChild(tr);
					td = document.createElement("td");
					td.innerHTML = "距离";
					tr.appendChild(td);
					td = document.createElement("td");
					td.innerHTML = "手牌";
					tr.appendChild(td);
					td = document.createElement("td");
					td.innerHTML = "行动";
					tr.appendChild(td);
					td = document.createElement("td");
					td.innerHTML = "伤害";
					tr.appendChild(td);

					tr = document.createElement("tr");
					table.appendChild(tr);
					td = document.createElement("td");
					if (node == game.me || !game.me || !game.me.isIn()) {
						td.innerHTML = "-";
					} else {
						var dist1 = get.numStr(Math.max(1, game.me.distanceTo(node)));
						var dist2 = get.numStr(Math.max(1, node.distanceTo(game.me)));
						if (dist1 == dist2) {
							td.innerHTML = dist1;
						} else {
							td.innerHTML = dist1 + "/" + dist2;
						}
					}
					tr.appendChild(td);
					td = document.createElement("td");
					let handcardLimit = node.getHandcardLimit();
					td.innerHTML = `${node.countCards("h")}/${handcardLimit >= 114514 ? "∞" : handcardLimit}`;
					tr.appendChild(td);
					td = document.createElement("td");
					td.innerHTML = node.phaseNumber;
					tr.appendChild(td);
					td = document.createElement("td");

					(function () {
						num = 0;
						for (var j = 0; j < node.stat.length; j++) {
							if (typeof node.stat[j].damage == "number") num += node.stat[j].damage;
						}
						td.innerHTML = num;
					})();
					tr.appendChild(td);
					table.style.width = "calc(100% - 20px)";
					table.style.marginLeft = "10px";

					uiintro.content.appendChild(table);
					if (!lib.config.show_favourite) {
						table.style.paddingBottom = "5px";
					}
				}
				if (!simple || get.is.phoneLayout()) {
					var es = node.getCards("e");
					for (var i = 0; i < es.length; i++) {
						const special = [es[i]].concat(es[i].cards || []).find(j => j.name == es[i].name && lib.card[j.name]?.cardPrompt);
						var str = special ? lib.card[special.name].cardPrompt(special, node) : lib.translate[es[i].name + "_info"];
						uiintro.add('<div><div class="skill">' + es[i].outerHTML + "</div><div>" + str + "</div></div>");
						uiintro.content.lastChild.querySelector(".skill>.card").style.transform = "";

						if (lib.translate[es[i].name + "_append"]) {
							uiintro.add('<div class="text">' + lib.translate[es[i].name + "_append"] + "</div>");
						}
					}
					var js = node.getCards("j");
					for (var i = 0; i < js.length; i++) {
						if (js[i].viewAs && js[i].viewAs != js[i].name) {
							let html = js[i].outerHTML;
							let cardInfo = lib.card[js[i].viewAs],
								showCardIntro = true;
							if (cardInfo.blankCard) {
								var cardOwner = get.owner(js[i]);
								if (cardOwner && !cardOwner.isUnderControl(true)) showCardIntro = false;
							}
							if (!showCardIntro) {
								html = ui.create.button(js[i], "blank").outerHTML;
							}
							uiintro.add('<div><div class="skill">' + html + "</div><div>" + lib.translate[js[i].viewAs] + "：" + lib.translate[js[i].viewAs + "_info"] + "</div></div>");
						} else {
							uiintro.add('<div><div class="skill">' + js[i].outerHTML + "</div><div>" + lib.translate[js[i].name + "_info"] + "</div></div>");
						}
						uiintro.content.lastChild.querySelector(".skill>.card").style.transform = "";
					}
					if (get.is.phoneLayout()) {
						var markCoutainer = ui.create.div(".mark-container.marks");
						for (var i in node.marks) {
							var nodemark = node.marks[i].cloneNode(true);
							nodemark.classList.add("pointerdiv");
							nodemark.link = node.marks[i];
							nodemark.style.transform = "";
							markCoutainer.appendChild(nodemark);
							nodemark.listen(function () {
								uiintro.noresume = true;
								var rect = this.link.getBoundingClientRect();
								ui.click.intro.call(this.link, {
									clientX: rect.left + rect.width,
									clientY: rect.top + rect.height / 2,
								});
								if (lib.config.touchscreen) {
									uiintro._close();
								}
							});
						}
						if (markCoutainer.childElementCount) {
							uiintro.addText("标记");
							uiintro.add(markCoutainer);
						}
					}
				}
				if (!game.observe && _status.gameStarted && game.me && node != game.me) {
					ui.throwEmotion = [];
					uiintro.addText("发送交互表情");
					var click = function () {
						if (_status.dragged) return;
						if (_status.justdragged) return;
						if (_status.throwEmotionWait) return;
						var emotion = this.link;
						if (game.online) {
							game.send("throwEmotion", node, emotion);
						} else game.me.throwEmotion(node, emotion);
						uiintro._close();
						if (!lib.config[`${swTool.myURL()}cancleInteractLimit`]) _status.throwEmotionWait = true;
						setTimeout(
							function () {
								_status.throwEmotionWait = false;
								if (ui.throwEmotion) {
									for (var i of ui.throwEmotion) i.classList.remove("exclude");
								}
							},
							emotion == "flower" || emotion == "egg" ? 500 : 5000
						);
					};
					//连续交互
					var click2 = function () {
						if (_status.dragged) return;
						if (_status.justdragged) return;
						if (_status.throwEmotionWait) return;
						var emotion = this.link.slice(0, -4);
						if (game.online) {
							game.send("throwEmotion", node, emotion);
						} else game.me.throwEmotion(node, emotion);
						uiintro._close();
						if (!lib.config[`${swTool.myURL()}cancleInteractLimit`]) _status.throwEmotionWait = true;
						setTimeout(
							function () {
								_status.throwEmotionWait = false;
								if (ui.throwEmotion) {
									for (var i of ui.throwEmotion) i.classList.remove("exclude");
								}
							},
							emotion == "flower" || emotion == "egg" ? 500 : 5000
						);
						if (emotion == "egg") {
							for (var i = 0; i < 8; i++) {
								setTimeout(function () {
									if (game.online) {
										game.send("throwEmotion", node, emotion);
									} else game.me.throwEmotion(node, emotion);
								}, 150 * (i + 1));
							}
							for (var i = 9; i < 10; i++) {
								setTimeout(function () {
									if (game.online) {
										game.send("throwEmotion", node, "shoe");
									} else game.me.throwEmotion(node, "shoe");
								}, 170 * (i + 1));
							}
						}
						else {
							for (var i = 0; i < 7; i++) {
								setTimeout(function () {
									if (game.online) {
										game.send("throwEmotion", node, emotion);
									} else game.me.throwEmotion(node, emotion);
								}, 150 * (i + 1));
							}
							for (var i = 8; i < 10; i++) {
								setTimeout(function () {
									if (game.online) {
										game.send("throwEmotion", node, "wine");
									} else game.me.throwEmotion(node, "wine");
								}, 170 * (i + 1));
							}
						}
						
					};
					//结束
					var td;
					var table = document.createElement("div");
					table.classList.add("add-setting");
					table.style.margin = "0";
					table.style.width = "100%";
					table.style.position = "relative";
					var listi = ["flower", "egg"];
					for (var i = 0; i < listi.length; i++) {
						td = ui.create.div(".menubutton.reduce_radius.pointerdiv.tdnode");
						ui.throwEmotion.add(td);
						if (_status.throwEmotionWait) td.classList.add("exclude");
						td.link = listi[i];
						table.appendChild(td);
						td.innerHTML = "<span>" + get.translation(listi[i]) + "</span>";
						td.addEventListener(lib.config.touchscreen ? "touchend" : "click", click);
					}
					uiintro.content.appendChild(table);
					table = document.createElement("div");
					table.classList.add("add-setting");
					table.style.margin = "0";
					table.style.width = "100%";
					table.style.position = "relative";
					var listi = ["wine", "shoe"];
					if (game.me.storage.zhuSkill_shanli) listi = ["yuxisx", "jiasuo"];
					for (var i = 0; i < listi.length; i++) {
						td = ui.create.div(".menubutton.reduce_radius.pointerdiv.tdnode");
						ui.throwEmotion.add(td);
						if (_status.throwEmotionWait) td.classList.add("exclude");
						td.link = listi[i];
						table.appendChild(td);
						td.innerHTML = "<span>" + get.translation(listi[i]) + "</span>";
						td.addEventListener(lib.config.touchscreen ? "touchend" : "click", click);
					}
					uiintro.content.appendChild(table);
					//连续交互
					var table = document.createElement("div");
					table.classList.add("add-setting");
					table.style.margin = "0";
					table.style.width = "100%";
					table.style.position = "relative";
					var listi = ["flowerSpam", "eggSpam"];
					for (var i = 0; i < listi.length; i++) {
						td = ui.create.div(".menubutton.reduce_radius.pointerdiv.tdnode");
						ui.throwEmotion.add(td);
						if (_status.throwEmotionWait) td.classList.add("exclude");
						td.link = listi[i];
						table.appendChild(td);
						td.innerHTML = "<span>" + get.translation(listi[i]) + "</span>";
						td.addEventListener(lib.config.touchscreen ? "touchend" : "click", click2);
					}
					uiintro.content.appendChild(table);
					//结束
				}

				var modepack = lib.characterPack["mode_" + get.mode()];
				if (lib.config.show_favourite && lib.character[node.name] && game.players.includes(node) && (!modepack || !modepack[node.name]) && (!simple || get.is.phoneLayout())) {
					var addFavourite = ui.create.div(".text.center.pointerdiv");
					addFavourite.link = node.name;
					if (lib.config.favouriteCharacter.includes(node.name)) {
						addFavourite.innerHTML = "移除收藏";
					} else {
						addFavourite.innerHTML = "添加收藏";
					}
					addFavourite.listen(ui.click.favouriteCharacter);
					uiintro.add(addFavourite);
				}
				if (!simple || get.is.phoneLayout()) {
					if ((lib.config.change_skin || lib.skin) && !node.isUnseen()) {
						var num = 1;
						var introadded = false;
						var createButtons = function (num, avatar2) {
							if (!introadded) {
								introadded = true;
								uiintro.add('<div class="text center">更改皮肤</div>');
							}
							var buttons = ui.create.div(".buttons.smallzoom.scrollbuttons");
							lib.setMousewheel(buttons);
							var nameskin = avatar2 ? node.name2 : node.name1;
							var nameskin2 = nameskin;
							var gzbool = false;
							if (nameskin.startsWith("gz_shibing")) {
								nameskin = nameskin.slice(3, 11);
							} else if (nameskin.startsWith("gz_")) {
								nameskin = nameskin.slice(3);
								gzbool = true;
							}
							for (var i = 0; i <= num; i++) {
								var button = ui.create.div(".button.character.pointerdiv", buttons, function () {
									if (this._link) {
										if (avatar2) {
											lib.config.skin[nameskin] = this._link;
											node.node.avatar2.style.backgroundImage = this.style.backgroundImage;
										} else {
											lib.config.skin[nameskin] = this._link;
											node.node.avatar.style.backgroundImage = this.style.backgroundImage;
										}
									} else {
										delete lib.config.skin[nameskin];
										if (avatar2) {
											if (gzbool && lib.character[nameskin2].hasSkinInGuozhan && lib.config.mode_config.guozhan.guozhanSkin) node.node.avatar2.setBackground(nameskin2, "character");
											else node.node.avatar2.setBackground(nameskin, "character");
										} else {
											if (gzbool && lib.character[nameskin2].hasSkinInGuozhan && lib.config.mode_config.guozhan.guozhanSkin) node.node.avatar.setBackground(nameskin2, "character");
											else node.node.avatar.setBackground(nameskin, "character");
										}
									}
									game.saveConfig("skin", lib.config.skin);
								});
								button._link = i;
								if (i) {
									button.setBackgroundImage("image/skin/" + nameskin + "/" + i + ".jpg");
								} else {
									if (gzbool && lib.character[nameskin2].hasSkinInGuozhan && lib.config.mode_config.guozhan.guozhanSkin) button.setBackground(nameskin2, "character", "noskin");
									else button.setBackground(nameskin, "character", "noskin");
								}
							}
							uiintro.add(buttons);
						};
						var loadImage = function (avatar2) {
							var img = new Image();
							img.onload = function () {
								num++;
								loadImage(avatar2);
							};
							img.onerror = function () {
								num--;
								if (num) {
									createButtons(num, avatar2);
								}
								if (!avatar2) {
									if (!node.classList.contains("unseen2") && node.name2) {
										num = 1;
										loadImage(true);
									}
								}
							};
							var nameskin = avatar2 ? node.name2 : node.name1;
							var nameskin2 = nameskin;
							var gzbool = false;
							if (nameskin.startsWith("gz_shibing")) {
								nameskin = nameskin.slice(3, 11);
							} else if (nameskin.startsWith("gz_")) {
								nameskin = nameskin.slice(3);
								gzbool = true;
							}
							img.src = lib.assetURL + "image/skin/" + nameskin + "/" + num + ".jpg";
						};
						if (lib.config.change_skin) {
							if (!node.isUnseen(0)) {
								loadImage();
							} else if (node.name2) {
								loadImage(true);
							}
						} else {
							setTimeout(function () {
								var nameskin1 = node.name1;
								var nameskin2 = node.name2;
								if (nameskin1 && nameskin1.startsWith("gz_")) {
									nameskin1 = nameskin1.slice(3);
								}
								if (nameskin2 && nameskin2.startsWith("gz_")) {
									nameskin2 = nameskin2.slice(3);
								}
								if (!node.isUnseen(0) && lib.skin[nameskin1]) {
									createButtons(lib.skin[nameskin1]);
								}
								if (!node.isUnseen(1) && lib.skin[nameskin2]) {
									createButtons(lib.skin[nameskin2], true);
								}
							});
						}
					}
				}

				uiintro.add(ui.create.div(".placeholder.slim"));
			} else if (node.classList.contains("mark") && node.info && node.parentNode && node.parentNode.parentNode && node.parentNode.parentNode.classList.contains("player")) {
				var info = node.info;
				var player = node.parentNode.parentNode;
				if (info.name) {
					if (typeof info.name == "function") {
						var named = info.name(player.storage[node.skill], player);
						if (named) {
							uiintro.add(named);
						}
					} else {
						uiintro.add(info.name);
					}
				} else if (info.name !== false) {
					uiintro.add(get.translation(node.skill));
				}
				if (typeof info.id == "string" && info.id.startsWith("subplayer") && player.isUnderControl(true) && player.storage[info.id] && !_status.video) {
					var storage = player.storage[info.id];
					uiintro.addText("当前体力：" + storage.hp + "/" + storage.maxHp);
					if (storage.hs.length) {
						uiintro.addText("手牌区");
						uiintro.addSmall(storage.hs);
					}
					if (storage.es.length) {
						uiintro.addText("装备区");
						uiintro.addSmall(storage.es);
					}
				}
				if (typeof info.mark == "function") {
					var stint = info.mark(uiintro, player.storage[node.skill], player);
					if (stint) {
						var placetext = uiintro.add('<div class="text" style="display:inline">' + stint + "</div>");
						if (!stint.startsWith('<div class="skill"')) {
							uiintro._place_text = placetext;
						}
						// if(stint.length<=100){
						// 	uiintro.add('<div class="text center">'+stint+'</div>');
						// }
						// else{
						// 	uiintro.add('<div class="text">'+stint+'</div>');
						// }
					}
				} else {
					var stint = get.storageintro(info.content, player.storage[node.skill], player, uiintro, node.skill);
					if (stint) {
						if (stint[0] == "@") {
							uiintro.add('<div class="caption">' + stint.slice(1) + "</div>");
						} else {
							var placetext = uiintro.add('<div class="text" style="display:inline">' + stint + "</div>");
							if (!stint.startsWith('<div class="skill"')) {
								uiintro._place_text = placetext;
							}
						}
						// else if(stint.length<=100){
						// 	uiintro.add('<div class="text center">'+stint+'</div>');
						// }
						// else{
						// 	uiintro.add('<div class="text">'+stint+'</div>');
						// }
					}
				}
				uiintro.add(ui.create.div(".placeholder.slim"));
			} else if (node.classList.contains("card")) {
				//卡牌长按介绍
				if (ui.arena.classList.contains("observe") && node.parentNode.classList.contains("handcards")) {
					return;
				}
				var name = node.name;
				if (node.parentNode.cardMod) {
					var moded = false;
					for (var i in node.parentNode.cardMod) {
						var item = node.parentNode.cardMod[i](node);
						if (Array.isArray(item)) {
							moded = true;
							uiintro.add(item[0]);
							uiintro._place_text = uiintro.add('<div class="text" style="display:inline">' + item[1] + "</div>");
						}
					}
					if (moded) return uiintro;
				}
				if (node.link && node.link.name && lib.card[node.link.name]) {
					name = node.link.name;
				}
				var cardPosition = get.position(node);
				if ((cardPosition === "e" || cardPosition === "j") && node.viewAs && node.viewAs != name) {
					uiintro.add(get.translation(node.viewAs));
					var cardInfo = lib.card[node.viewAs],
						showCardIntro = true;
					var cardOwner = get.owner(node);
					if (cardInfo.blankCard) {
						if (cardOwner && !cardOwner.isUnderControl(true)) showCardIntro = false;
					}
					if (cardOwner) {
						var sourceVCard = cardOwner.getVCards(cardPosition).find(card => card.cards?.includes(node));
						if (showCardIntro && sourceVCard) uiintro.add('<div class="text center">（' + get.translation(get.translation(sourceVCard.cards)) + "）</div>");
					}
					// uiintro.add(get.translation(node.viewAs)+'<br><div class="text center" style="padding-top:5px;">（'+get.translation(node)+'）</div>');
					uiintro.nosub = true;
					name = node.viewAs;
				} else {
					uiintro.add(get.translation(node));
				}
				if (node._banning) {
					var clickBanned = function () {
						var banned = lib.config[this.bannedname] || [];
						if (banned.includes(name)) {
							banned.remove(name);
						} else {
							banned.push(name);
						}
						game.saveConfig(this.bannedname, banned);
						this.classList.toggle("on");
						if (node.updateBanned) {
							node.updateBanned();
						}
					};
					var modeorder = lib.config.modeorder || [];
					for (var i in lib.mode) {
						modeorder.add(i);
					}
					var list = [];
					uiintro.contentContainer.listen(function (e) {
						ui.click.touchpop();
						e.stopPropagation();
					});
					for (var i = 0; i < modeorder.length; i++) {
						if (node._banning == "online") {
							if (!lib.mode[modeorder[i]].connect) continue;
						} else if (modeorder[i] == "connect" || modeorder[i] == "brawl") {
							continue;
						}
						if (lib.config.all.mode.includes(modeorder[i])) {
							list.push(modeorder[i]);
						}
					}
					if (lib.card[name] && lib.card[name].type == "trick") list.push("zhinang_tricks");
					var page = ui.create.div(".menu-buttons.configpopped", uiintro.content);
					var banall = false;
					for (var i = 0; i < list.length; i++) {
						var cfg = ui.create.div(".config", list[i] == "zhinang_tricks" ? "设为智囊" : lib.translate[list[i]] + "模式", page);
						cfg.classList.add("toggle");
						if (list[i] == "zhinang_tricks") {
							cfg.bannedname = (node._banning == "offline" ? "" : "connect_") + "zhinang_tricks";
						} else if (node._banning == "offline") {
							cfg.bannedname = list[i] + "_bannedcards";
						} else {
							cfg.bannedname = "connect_" + list[i] + "_bannedcards";
						}
						cfg.listen(clickBanned);
						ui.create.div(ui.create.div(cfg));
						var banned = lib.config[cfg.bannedname] || [];
						if (banned.includes(name) == (list[i] == "zhinang_tricks")) {
							cfg.classList.add("on");
							banall = true;
						}
					}
					ui.create.div(".menubutton.pointerdiv", banall ? "全部禁用" : "全部启用", uiintro.content, function () {
						if (this.innerHTML == "全部禁用") {
							for (var i = 0; i < page.childElementCount; i++) {
								if (page.childNodes[i].bannedname.indexOf("zhinang_tricks") == -1 && page.childNodes[i].bannedname && page.childNodes[i].classList.contains("on")) {
									clickBanned.call(page.childNodes[i]);
								}
							}
							this.innerHTML = "全部启用";
						} else {
							for (var i = 0; i < page.childElementCount; i++) {
								if (page.childNodes[i].bannedname.indexOf("zhinang_tricks") == -1 && page.childNodes[i].bannedname && !page.childNodes[i].classList.contains("on")) {
									clickBanned.call(page.childNodes[i]);
								}
							}
							this.innerHTML = "全部禁用";
						}
					}).style.marginTop = "-10px";
					ui.create.div(".placeholder.slim", uiintro.content);
				} else {
					if (lib.translate[name + "_info"]) {
						if (!uiintro.nosub) {
							if (lib.card[name] && lib.card[name].derivation) {
								if (typeof lib.card[name].derivation == "string") {
									uiintro.add('<div class="text center">来源：' + get.translation(lib.card[name].derivation) + "</div>");
								} else if (lib.card[name].derivationpack) {
									uiintro.add('<div class="text center">来源：' + get.translation(lib.card[name].derivationpack + "_card_config") + "包</div>");
								}
							}
							let typeinfo = "";
							if (lib.card[name] && lib.card[name].unique) {
								typeinfo += "特殊" + get.translation(lib.card[name].type) + "牌";
							} else if (lib.card[name] && lib.card[name].type && lib.translate[lib.card[name].type]) {
								typeinfo += get.translation(lib.card[name].type) + "牌";
							}
							let vcard = get
								.owner(node)
								?.getVCards(get.position(node))
								?.find(card => card.cards?.includes(node));
							if (get.subtypes(vcard || node, get.owner(node))?.length) {
								typeinfo +=
									"-" +
									get
										.subtypes(vcard || node, get.owner(node))
										.map(type => get.translation(type))
										.join("/");
							}
							if (typeinfo) {
								uiintro.add('<div class="text center">' + typeinfo + "</div>");
							}
							if (lib.card[name].unique && lib.card[name].type == "equip") {
								if (lib.cardPile.guozhan && lib.cardPack.guozhan.includes(name)) {
									uiintro.add('<div class="text center">专属装备</div>').style.marginTop = "-5px";
								} else {
									uiintro.add('<div class="text center">特殊装备</div>').style.marginTop = "-5px";
								}
							}
							if (lib.card[name] && lib.card[name].addinfomenu) {
								uiintro.add('<div class="text center">' + lib.card[name].addinfomenu + "</div>");
							}
							if (get.subtype(name, false) == "equip1") {
								var added = false;
								if (lib.card[node.name] && lib.card[node.name].distance) {
									var dist = lib.card[node.name].distance;
									if (dist.attackFrom) {
										added = true;
										uiintro.add('<div class="text center">攻击范围：' + (-dist.attackFrom + 1) + "</div>");
									}
								}
								if (!added) {
									uiintro.add('<div class="text center">攻击范围：1</div>');
								}
							}
						}
						if (lib.card[name].cardPrompt) {
							var str = lib.card[name].cardPrompt(node.link || node, player),
								placetext = uiintro.add('<div class="text" style="display:inline">' + str + "</div>");
							if (!str.startsWith('<div class="skill"')) {
								uiintro._place_text = placetext;
							}
						} else if (lib.translate[name + "_info"]) {
							var placetext = uiintro.add('<div class="text" style="display:inline">' + lib.translate[name + "_info"] + "</div>");
							if (!lib.translate[name + "_info"].startsWith('<div class="skill"')) {
								uiintro._place_text = placetext;
							}
						}
						if (get.is.yingbianConditional(node.link || node)) {
							const yingbianEffects = get.yingbianEffects(node.link || node);
							if (!yingbianEffects.length) {
								const defaultYingbianEffect = get.defaultYingbianEffect(node.link || node);
								if (lib.yingbian.prompt.has(defaultYingbianEffect)) yingbianEffects.push(defaultYingbianEffect);
							}
							if (yingbianEffects.length && showCardIntro) uiintro.add(`<div class="text" style="font-family: yuanli">应变：${yingbianEffects.map(value => lib.yingbian.prompt.get(value)).join("；")}</div>`);
						}
						if (lib.translate[name + "_append"]) {
							uiintro.add('<div class="text" style="display:inline">' + lib.translate[name + "_append"] + "</div>");
						}
					}
					uiintro.add(ui.create.div(".placeholder.slim"));
				}
			} else if (node.classList.contains("character")) {
				const character = node.link,
					characterInfo = get.character(node.link);
				let capt = get.translation(character);
				if (characterInfo) {
					const infoSex = characterInfo[0];
					if (infoSex && lib.config.show_sex) capt += `&nbsp;&nbsp;${infoSex == "none" ? "无" : lib.translate[infoSex]}`;
					const infoGroup = characterInfo[1];
					if (infoGroup && lib.config.show_group) {
						const group = get.is.double(character, true);
						if (group) capt += `&nbsp;&nbsp;${group.map(value => get.translation(value)).join("/")}`;
						else capt += `&nbsp;&nbsp;${lib.translate[infoGroup]}`;
					}
				}
				uiintro.add(capt);

				if (lib.characterTitle[node.link]) {
					uiintro.addText(get.colorspan(lib.characterTitle[node.link]));
				}

				if (get.characterInitFilter(node.link)) {
					const initFilters = get.characterInitFilter(node.link).filter(tag => {
						if (!lib.characterInitFilter[node.link]) return true;
						return lib.characterInitFilter[node.link](tag) !== false;
					});
					if (initFilters.length) {
						const str = initFilters.reduce((strx, stry) => strx + lib.InitFilter[stry] + "<br>", "").slice(0, -4);
						uiintro.addText(str);
					}
				}

				if (node._banning) {
					var clickBanned = function () {
						var banned = lib.config[this.bannedname] || [];
						if (banned.includes(character)) {
							banned.remove(character);
						} else {
							banned.push(character);
						}
						game.saveConfig(this.bannedname, banned);
						this.classList.toggle("on");
						if (node.updateBanned) {
							node.updateBanned();
						}
					};
					var modeorder = lib.config.modeorder || [];
					for (var i in lib.mode) {
						modeorder.add(i);
					}
					var list = [];
					uiintro.contentContainer.listen(function (e) {
						ui.click.touchpop();
						e.stopPropagation();
					});
					for (var i = 0; i < modeorder.length; i++) {
						if (node._banning == "online") {
							if (!lib.mode[modeorder[i]].connect) continue;
							if (!lib.config["connect_" + modeorder[i] + "_banned"]) {
								lib.config["connect_" + modeorder[i] + "_banned"] = [];
							}
						} else if (modeorder[i] == "connect" || modeorder[i] == "brawl") {
							continue;
						}
						if (lib.config.all.mode.includes(modeorder[i])) {
							list.push(modeorder[i]);
						}
					}
					var page = ui.create.div(".menu-buttons.configpopped", uiintro.content);
					var banall = false;
					for (var i = 0; i < list.length; i++) {
						var cfg = ui.create.div(".config", lib.translate[list[i]] + "模式", page);
						cfg.classList.add("toggle");
						if (node._banning == "offline") {
							cfg.bannedname = list[i] + "_banned";
						} else {
							cfg.bannedname = "connect_" + list[i] + "_banned";
						}
						cfg.listen(clickBanned);
						ui.create.div(ui.create.div(cfg));
						var banned = lib.config[cfg.bannedname] || [];
						if (!banned.includes(character)) {
							cfg.classList.add("on");
							banall = true;
						}
					}
					if (node._banning == "offline") {
						var cfg = ui.create.div(".config", "随机选将可用", page);
						cfg.classList.add("toggle");
						cfg.listen(function () {
							this.classList.toggle("on");
							if (this.classList.contains("on")) {
								lib.config.forbidai_user.remove(character);
							} else {
								lib.config.forbidai_user.add(character);
							}
							game.saveConfig("forbidai_user", lib.config.forbidai_user);
						});
						ui.create.div(ui.create.div(cfg));
						if (!lib.config.forbidai_user.includes(character)) {
							cfg.classList.add("on");
						}
					}
					ui.create.div(".menubutton.pointerdiv", banall ? "全部禁用" : "全部启用", uiintro.content, function () {
						if (this.innerHTML == "全部禁用") {
							for (var i = 0; i < page.childElementCount; i++) {
								if (page.childNodes[i].bannedname && page.childNodes[i].classList.contains("on")) {
									clickBanned.call(page.childNodes[i]);
								}
							}
							this.innerHTML = "全部启用";
						} else {
							for (var i = 0; i < page.childElementCount; i++) {
								if (page.childNodes[i].bannedname && !page.childNodes[i].classList.contains("on")) {
									clickBanned.call(page.childNodes[i]);
								}
							}
							this.innerHTML = "全部禁用";
						}
					}).style.marginTop = "-10px";
					ui.create.div(".placeholder.slim", uiintro.content);
				} else {
					var skills = get.character(character, 3);
					for (i = 0; i < skills.length; i++) {
						if (lib.translate[skills[i] + "_info"]) {
							if (lib.translate[skills[i] + "_ab"]) translation = lib.translate[skills[i] + "_ab"];
							else {
								translation = get.translation(skills[i]);
								if (!lib.skill[skills[i]].nobracket) translation = `【${translation.slice(0, 2)}】`;
							}

							uiintro.add('<div><div class="skill">' + translation + "</div><div>" + get.skillInfoTranslation(skills[i]) + "</div></div>");

							if (lib.translate[skills[i] + "_append"]) {
								uiintro._place_text = uiintro.add('<div class="text">' + lib.translate[skills[i] + "_append"] + "</div>");
							}
						}
					}
					var modepack = lib.characterPack["mode_" + get.mode()];
					if (lib.config.show_favourite && lib.character[node.link] && (!modepack || !modepack[node.link]) && (!simple || get.is.phoneLayout())) {
						var addFavourite = ui.create.div(".text.center.pointerdiv");
						addFavourite.link = node.link;
						addFavourite.style.marginBottom = "15px";
						if (lib.config.favouriteCharacter.includes(node.link)) {
							addFavourite.innerHTML = "移除收藏";
						} else {
							addFavourite.innerHTML = "添加收藏";
						}
						addFavourite.listen(ui.click.favouriteCharacter);
						uiintro.add(addFavourite);
					} else {
						uiintro.add(ui.create.div(".placeholder.slim"));
					}
					var addskin = false;
					if (node.parentNode.classList.contains("menu-buttons")) {
						addskin = !lib.config.show_charactercard;
					} else {
						addskin = lib.config.change_skin || lib.skin;
					}
					if (addskin && (!simple || get.is.phoneLayout())) {
						var num = 1;
						var introadded = false;
						var nameskin = node.link;
						var nameskin2 = nameskin;
						var gzbool = false;
						if (nameskin.startsWith("gz_shibing")) {
							nameskin = nameskin.slice(3, 11);
						} else if (nameskin.startsWith("gz_")) {
							nameskin = nameskin.slice(3);
							gzbool = true;
						}
						var createButtons = function (num) {
							if (!num) return;
							if (!introadded) {
								introadded = true;
								uiintro.add('<div class="text center">更改皮肤</div>');
							}
							var buttons = ui.create.div(".buttons.smallzoom.scrollbuttons");
							lib.setMousewheel(buttons);
							for (var i = 0; i <= num; i++) {
								var button = ui.create.div(".button.character.pointerdiv", buttons, function () {
									if (this._link) {
										lib.config.skin[nameskin] = this._link;
										node.style.backgroundImage = this.style.backgroundImage;
										game.saveConfig("skin", lib.config.skin);
									} else {
										delete lib.config.skin[nameskin];
										if (gzbool && lib.character[nameskin2].hasSkinInGuozhan && lib.config.mode_config.guozhan.guozhanSkin) node.setBackground(nameskin2, "character");
										else node.setBackground(nameskin, "character");
										game.saveConfig("skin", lib.config.skin);
									}
								});
								button._link = i;
								if (i) {
									button.setBackgroundImage("image/skin/" + nameskin + "/" + i + ".jpg");
								} else {
									if (gzbool && lib.character[nameskin2].hasSkinInGuozhan && lib.config.mode_config.guozhan.guozhanSkin) button.setBackground(nameskin2, "character", "noskin");
									else button.setBackground(nameskin, "character", "noskin");
								}
							}
							uiintro.add(buttons);
						};
						var loadImage = function () {
							var img = new Image();
							img.onload = function () {
								num++;
								loadImage();
							};
							img.onerror = function () {
								num--;
								createButtons(num);
							};
							img.src = lib.assetURL + "image/skin/" + nameskin + "/" + num + ".jpg";
						};
						if (lib.config.change_skin) {
							loadImage();
						} else {
							setTimeout(function () {
								createButtons(lib.skin[nameskin]);
							});
						}
					}
				}
			} else if (node.classList.contains("equips") && ui.arena.classList.contains("selecting")) {
				(function () {
					uiintro.add("选择装备");
					uiintro.addSmall(
						Array.from(node.childNodes).filter(node => !node.classList.contains("emptyequip") && !node.classList.contains("feichu")),
						true
					);
					uiintro.clickintro = true;
					ui.control.hide();
					uiintro._onclose = function () {
						ui.control.show();
					};
					var confirmbutton;
					for (var i = 0; i < uiintro.buttons.length; i++) {
						var button = uiintro.buttons[i];
						button.classList.add("pointerdiv");
						if (button.link.classList.contains("selected")) {
							button.classList.add("selected");
						}
						button.listen(function (e) {
							ui.click.card.call(this.link, "popequip");
							ui.click.window.call(ui.window, e);
							if (this.link.classList.contains("selected")) {
								this.classList.add("selected");
							} else {
								this.classList.remove("selected");
							}
							if (ui.confirm && ui.confirm.str && ui.confirm.str.includes("o")) {
								confirmbutton.classList.remove("disabled");
							} else {
								confirmbutton.classList.add("disabled");
							}
						});
					}
					var buttoncontainer = uiintro.add(ui.create.div());
					buttoncontainer.style.display = "block";
					confirmbutton = ui.create.div(
						".menubutton.large.pointerdiv",
						"确定",
						function () {
							if (ui.confirm && ui.confirm.str && ui.confirm.str.includes("o")) {
								uiintro._clickintro();
								ui.click.ok(ui.confirm.firstChild);
							}
						},
						buttoncontainer
					);
					confirmbutton.style.position = "relative";
					setTimeout(function () {
						if (ui.confirm && ui.confirm.str && ui.confirm.str.includes("o")) {
							confirmbutton.classList.remove("disabled");
						} else {
							confirmbutton.classList.add("disabled");
						}
					}, 300);
				})();
			} else if (node.classList.contains("identity") && node.dataset.career) {
				var career = node.dataset.career;
				uiintro.add(get.translation(career));
				uiintro.add('<div class="text center" style="padding-bottom:5px">' + lib.translate["_" + career + "_skill_info"] + "</div>");
			} else if (node.classList.contains("skillbar")) {
				if (node == ui.friendBar) {
					uiintro.add("友方怒气值");
					uiintro.add('<div class="text center" style="padding-bottom:5px">' + _status.friendRage + "/100</div>");
				} else if (node == ui.enemyBar) {
					uiintro.add("敌方怒气值");
					uiintro.add('<div class="text center" style="padding-bottom:5px">' + _status.enemyRage + "/100</div>");
				}
			} else if (node.parentNode == ui.historybar) {
				if (node.dead) {
					if (!node.source || node.source == node.player) {
						uiintro.add('<div class="text center">' + get.translation(node.player) + "阵亡</div>");
						uiintro.addSmall([node.player]);
					} else {
						uiintro.add('<div class="text center">' + get.translation(node.player) + "被" + get.translation(node.source) + "杀害</div>");
						uiintro.addSmall([node.source]);
					}
				}
				if (node.skill) {
					uiintro.add('<div class="text center">' + get.translation(node.skill) + "</div>");
					uiintro._place_text = uiintro.add('<div class="text" style="display:inline">' + get.translation(node.skill, "info") + "</div>");
				}
				if (node.targets && get.itemtype(node.targets) == "players") {
					uiintro.add('<div class="text center">目标</div>');
					uiintro.addSmall(node.targets);
				}
				if (node.players && node.players.length > 1) {
					uiintro.add('<div class="text center">使用者</div>');
					uiintro.addSmall(node.players);
				}
				if (node.cards && node.cards.length) {
					uiintro.add('<div class="text center">卡牌</div>');
					uiintro.addSmall(node.cards);
				}
				for (var i = 0; i < node.added.length; i++) {
					uiintro.add(node.added[i]);
				}
				if (node.added.length) {
					uiintro.add(ui.create.div(".placeholder.slim"));
				}
				if (uiintro.content.firstChild) {
					uiintro.content.firstChild.style.paddingTop = "3px";
				}
			} else if (node.classList.contains("nodeintro")) {
				if (node.nodeTitle) uiintro.add(node.nodeTitle);
				uiintro._place_text = uiintro.add('<div class="text">' + node.nodeContent + "</div>");
			}
			if (lib.config.touchscreen) {
				lib.setScroll(uiintro.contentContainer);
			}
			return uiintro;
		}
	},
	closeWindowsError() {
		window.onerror = function (msg, src, line, column, err) { };
	},
	observeEnter() {
		lib.hooks.gameStart.push(function() {
			if(!_status.connectMode) return;
			lib.configOL.observePermission = {}
			for (var i = 0; i < game.players.length; i++) {
				if(game.players[i].isOnline() || game.players[i].nickname) {
					lib.configOL.observePermission[game.players[i].playerid] = 0
				}
				else {
					lib.configOL.observePermission[game.players[i].playerid] = 1//可以申请
				}
			}
			if (!ui.observeEnter) {
				ui.observeEnter = ui.create.system("旁观入场", null, true, true);
			}
			lib.setPopped(ui.observeEnter, function () {
				var uiintro = ui.create.dialog("hidden");

				uiintro.add("旁观入场");
				uiintro.add('<div class="text center">你可以点击按钮手动设定哪些位置可以被申请</div>');

				lib.configOL.observeRequesting ??= []
				//console.log(lib.configOL.observeRequesting)
				//console.log(lib.node.observing.map(player => player.ws.wsid))
				lib.configOL.observeRequesting = lib.configOL.observeRequesting.filter(p => {
					return lib.node.observing.map(player => player.ws.wsid).includes(p.ws)
				})

				function acceptFun(request, item) {
					return function (e) {
						e.stopPropagation();
						e.preventDefault();
						item.remove()
						const nickname = request.nickname
						const wsid = request.ws
						const playerId = request.playerId
						const roomId = game.roomId
						var have = false
						lib.node.observing.forEach(player => {
							if(player.ws.wsid === wsid) {
								have = true
								game.me.chat(`已经接受玩家 ${nickname} 的入场请求`)
								lib.configOL.observeRequesting = lib.configOL.observeRequesting.filter(p => {
									return p !== request
								})
								player.send((roomId, playerId) => {
									game.saveConfig("tmp_user_roomId", roomId);
									game.saveConfig("reconnect_info", [_status.ip, playerId, roomId]);
									alert("房主已同意你的入场请求，点击确定重连后可入场")
									game.reload();
								}, roomId, playerId)
							}
						})
						if(!have) game.me.chat(`玩家 ${nickname} 的请求已失效`)
					}
				}
				function refuseFun(request, item) {
					return function (e) {
						e.stopPropagation();
						e.preventDefault();
						item.remove();
						lib.configOL.observeRequesting = lib.configOL.observeRequesting.filter(p => {
							return p !== request
						})
					}
				}

				if(lib.configOL.observeRequesting) {
					var requestList = ui.create.div(".observeRequestContainer");
					for(let i in lib.configOL.observeRequesting) {
						let nickname = lib.configOL.observeRequesting[i].nickname
						let playerId = lib.configOL.observeRequesting[i].playerId
						let ws = lib.configOL.observeRequesting[i].ws
						let item = ui.create.div(".item", requestList);
						let itemName = ui.create.div(".itemName", item);
						let itemRequest = ui.create.div(".itemRequest", item);
						let itemBool = ui.create.div(".itemBool", item);
						let itemBoolAccept = ui.create.div(".itemBoolButton", itemBool);
						itemBoolAccept.addEventListener(lib.config.touchscreen ? "touchend" : "click", acceptFun(lib.configOL.observeRequesting[i], item));
						let itemBoolRefuse = ui.create.div(".itemBoolButton", itemBool);
						itemBoolRefuse.addEventListener(lib.config.touchscreen ? "touchend" : "click", refuseFun(lib.configOL.observeRequesting[i], item));
						itemName.textContent = nickname
						itemRequest.textContent = lib.playerOL[playerId]?.node?.name?.textContent || "[错误玩家]"
						let itemBoolAcceptText = ui.create.div(".text", itemBoolAccept);
						let itemBoolRefuseText = ui.create.div(".text", itemBoolRefuse);
						itemBoolAcceptText.textContent = "接受"
						itemBoolRefuseText.textContent = "拒绝"
						itemBoolRefuse.classList.add("right")
					}
					uiintro.add(requestList);
				}

				var table = ui.create.div(".observeContainer");

				function modifyState(button, state, player, noTip = false) {
					if(state == "可申请" || state == 0) {
						button.textContent = "禁止申请×"
						button.classList.remove('canEnter');
						button.classList.add('forbidEnter');
						lib.configOL.observePermission[player.playerid] = 0
					}
					else if(state == "禁止申请×" || state == 1){
						if((player.isOnline() || player.nickname) && !noTip) {
							if(confirm("当前位置疑似正有玩家，是否确认？")){
								button.textContent = "可申请"
								button.classList.remove('forbidEnter');
								button.classList.add('canEnter');
								lib.configOL.observePermission[player.playerid] = 1
							}
						}
						else {
							button.textContent = "可申请"
							button.classList.remove('forbidEnter');
							button.classList.add('canEnter');
							lib.configOL.observePermission[player.playerid] = 1
						}
					}
				}

				var click = function(item, player) {
					return function (e) {
						//alert(player)
						e.stopPropagation();
						e.preventDefault();
						modifyState(item, item.textContent, player)
					}
				}

				var player, added = false;
				for (var i = 0; i < game.players.length; i++) {
					added = true;
					let item = ui.create.div(".item", table);

					let avatar = ui.create.div(".avatar", item);
					avatar.style.backgroundImage = game.players[i].node.avatar.style.backgroundImage;
					let avatarName = ui.create.div(".avatarName", avatar);
					avatarName.textContent = game.players[i].nickname || "[电脑]";
					let avatarButton = ui.create.div(".avatarButton", avatar);

					modifyState(avatarButton, lib.configOL.observePermission[game.players[i].playerid] || 0, game.players[i], true)

					avatarButton.addEventListener(lib.config.touchscreen ? "touchend" : "click", click(avatarButton, game.players[i]));
				}
				// if (!added) {
				// 	uiintro.add('<div class="text center">（无重整角色）</div>');
				// 	uiintro.add(ui.create.div(".placeholder.slim"));
				// } else {
				//
				// }
				uiintro.add(table);
				return uiintro;
			}, 480)
		});
	},
	showSeat() {
		function updatePlayerSeat(player) {
			if (!player) return;
			const seat = player.getSeatNum();
			if (seat === 0) return;
			player.seat = seat;
			game.broadcastAll(function (player, seat) {
				if (!player.node.swSeat) {
					player.node.swSeat = ui.create.div('.swSeat', player);
				}
				player.node.swSeat.innerHTML = get.cnNumber(seat, true);
			}, player, seat);
		}
		lib.hooks.checkUpdate.push("showSeat", function(player) {
			const seat = player.getSeatNum();
			if (seat === 0) return;
			player.seat = seat;
			if (!player.node.swSeat) {
				player.node.swSeat = ui.create.div('.swSeat', player);
			}
			player.node.swSeat.innerHTML = get.cnNumber(seat, true);
		});
		lib.hooks.gameStart.push(function () {
			game.players.forEach(updatePlayerSeat);
		});
		const _oldgameSwapSeat = game.swapSeat
		game.swapSeat = function(player1, player2, prompt, behind, noanimate) {
			_oldgameSwapSeat.apply(this, arguments);
			game.broadcastAll((player1, player2) => {
				player1.seat = player1.getSeatNum();
				if (player1.node.seat) player1.node.seat.innerHTML = get.cnNumber(player1.seat, true);
				player2.seat = player2.getSeatNum();
				if (player2.node.seat) player2.node.seat.innerHTML = get.cnNumber(player2.seat, true);
			}, player1, player2)
		}
		const _oldgameSetSeatNum = game.setSeatNum
		game.setSeatNum = function() {
			_oldgameSetSeatNum.apply(this, arguments);
			updatePlayerSeat(this);
		}
	},
	skillAnimation() {
		lib.element.player.$skill = function(name, type, color, avatar) {
			//if (!decadeUI.config.gameAnimationEffect || !decadeUI.animation.gl) return lib.element.player.$skill.apply(this, arguments);
			if (typeof type != "string") type = "legend";
			if (!avatar) {
				this.playerfocus(1500);
				game.delay(2);
			} else {
				game.addVideo("playerfocus2");
				game.broadcastAll(function () {
					ui.arena.classList.add("playerfocus");
					setTimeout(function () {
						ui.arena.classList.remove("playerfocus");
					}, 3100);
				});
				game.delay(0, 3100);
			}
			var that = this;
			setTimeout(
				function () {
					game.broadcastAll(
						function (that, type, name, color, avatar) {
							// if (lib.config.animation && !lib.config.low_performance) {
							// 	if (game.chess) {
							// 		that["$" + type + "2"](1200);
							// 	} else {
							// 		that["$" + type](1200);
							// 	}
							// }
							if (name) {
								//that.$fullscreenpop(name, color, avatar);
								swTool.playSkillAnimation(that, name)
							}
						},
						that,
						type,
						name,
						color,
						avatar
					);
				},
				avatar ? 0 : 300
			);


		}
	},
}
const packs = {
	DIY,
}

Object.keys(config).forEach(s => {
	const name = s.slice(5)
	const item = lib.config[swTool.myURL() + s]
	if (item) {
		if (s.startsWith('game_') && typeof functions[name] === 'function') functions[name]()
		if (s.startsWith('pack_')) {
			_status.extensionCharacter ??= { }
			const pack = packs[name]
			_status.extensionCharacter[name] = pack
			game.import("character", () => pack)
			// 首次导入开启将包
			if (!lib.config[pack.name+'_character_pack_open']){
				lib.config.characters.add(pack.name);
				game.saveConfig('characters', lib.config.characters);
				game.saveConfig(pack.name + '_character_pack_open',true);
			};
		}
	}
})

//加载完毕后
lib.arenaReady ??= [];
lib.arenaReady.push(()=> {
	for (const p in _status.extensionCharacter) {
		const pack = packs[p]
		if(typeof pack.func === "function") {
			pack.func()
		}
		// if(pack.character) {
		// 	for(const key in pack.character) {
		// 		const img = lib.character[key]?.img;
		// 		if (typeof img === "string" && img.startsWith("http")) {
		// 			lib.character[key].img = `extension/${swTool.extensionName}/assets/character/${key}.jpg`
		// 		}
		// 		const skin = lib.characterSubstitute[key] || []
		// 		for (const item of skin) {
		// 			if (Array.isArray(item) && item.length > 1) {
		// 				for (let i = 0; i < item[1].length; i++) {
		// 					if (typeof item[1][i] === 'string' && item[1][i].startsWith('img:http')) {
		// 						item[1][i] = `img:extension/${swTool.extensionName}/assets/character/${item[0]}.jpg`;
		// 					}
		// 				}
		// 			}
		// 		}
		// 	}
		// }
	}
})

swTool.globalSkills._gameStart = {
	ruleSkill: true,
	nopop: true,
	direct: true,
	superCharlotte: true,
	firstDo: true,
	priority: 9999999,
	trigger: {
		player: "phaseBefore",
	},
	filter(event, player) {
		if (event.name == "phase" && game.phaseNumber != 0) return false;
		return true;
	},
	content() {
		game.callHook("gameStart", []);
	}
}

for (const s in swTool.globalSkills) lib.skill[s] = swTool.globalSkills[s]


